<template>
  <form class="pin_content">
    <div ref="pinbox" class="pin-box">
      <div v-for="(n,key) in props.length" :key="key" class="input" :class="`i${key}`">
        <el-input
          v-model="PIN[key]"
          type="password"
          @keyup.delete="bindKeyDel(key)"
          @keydown="bindKeyPress($event,key)"
          @input="bindInput($event,key)"
          @blur="bindBlur(key)"
        />
      </div>
    </div>
    <div v-if="props.isErr" class="err" v-html="props.errMsg" />
  </form>
</template>

<script>
export default {
  name: 'PIN'
}
</script>

<script setup>
import { ref, onMounted, watch, defineEmits, defineProps } from 'vue'

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  length: {
    type: Number,
    default: 6
  },
  isErr: {
    type: Boolean,
    default: false
  },
  errMsg: {
    type: String,
    default: 'Wait for x minutes to enter PIN. <br/>You have 2 more attempts to enter PIN.'
  }
})

const emit = defineEmits(['update:modelValue'])

// 输入框颜色
const inputBorderColor = ref(props.isErr ? '#FF5858' : '#E5E5E5')

// 输入值
const PIN = ref([])

// 是否退格
const isDel = ref(false)

// 錯誤提示
watch(
  () => props.isErr,
  (val) => {
    inputBorderColor.value = val ? '#FF5858' : '#E5E5E5'
  }
)

// 改变位数
watch(
  () => props.length,
  (n) => {
    PIN.value.length = n
  }
)

// 監聽值
watch(
  () => props.modelValue,
  (value) => {
    if (!value.length) {
      const arr = []
      arr.length = props.length

      arr.forEach((item, index) => {
        item = value[index]
      })

      PIN.value = arr

      // 光標還原
      const $input = pinbox.value.querySelector(`.input.i0 input`)
	  isDel.value = true
      $input.focus()
	  isDel.value = false
    }

    if (value.length == props.length) {
      PIN.value = value.split('')
    }
  }
)

// 光标操作
const pinbox = ref(null)

// 默认focus
onMounted(() => {
  const $input = pinbox.value.querySelector(`.input.i0 input`)
  setTimeout(() => {
    $input.focus()
  }, 200)
})

// 失去焦点事件
const bindBlur = (key) => {
  const $currInput = pinbox.value.querySelector(`.input.i${key} input`)
  if ((!PIN.value[key] && PIN.value[key] != 0 && !isDel.value) || PIN.value.join('').length == props.length) {
    $currInput?.focus()
  }
  isDel.value = false
}

// 按鍵操作
const currkeyCode = ref(null)
const keyDownVal = ref(undefined)
const bindKeyPress = ({ keyCode }, key) => {
  currkeyCode.value = keyCode
  keyDownVal.value = PIN.value[key]
}

// 退格
const bindKeyDel = (key, e) => {
  isDel.value = true
  const $prevInput = pinbox.value.querySelector(`.input.i${Number(key) - 1} input`)
  if (key > 0 && currkeyCode.value === 8) {
    if (keyDownVal.value == undefined) {
	  PIN.value[Number(key) - 1] = undefined
      $prevInput.focus()
    }
    PIN.value[key] = undefined
    emit('update:modelValue', PIN.value.join(''))
  }
  return false
}

// 值改变
const bindInput = (currVal, key) => {
  const $nextInput = pinbox.value.querySelector(`.input.i${Number(key) + 1} input`)
  const $prevInput = pinbox.value.querySelector(`.input.i${Number(key) - 1} input`)

  if (PIN.value.join('').length) {
    inputBorderColor.value = '#007580'
  } else {
    inputBorderColor.value = '#E5E5E5'
  }

  // 验证
  if (!/^[0-9]$/.test(currVal)) {
    if (currVal.length > 1) {
      PIN.value[key] = currVal[0]
      $nextInput?.focus()
    } else {
      PIN.value[key] = undefined
    }
    emit('update:modelValue', PIN.value.join(''))
    return
  }

  if (currVal && key < props.length - 1) {
    $nextInput.focus()
  }

  PIN.value[key] = currVal

  emit('update:modelValue', PIN.value.join(''))
}
</script>

<style scoped lang="scss">
.pin_content {
    height: 72px;
}
.pin-box {
    display: flex;
    justify-content: center;
    .input {
        width: 48px;
        height: 48px;
        margin: 0 4px;

        :deep(.el-input__inner) {
            width: 48px;
            height: 48px;
            line-height: 48px;
            border-color: v-bind(inputBorderColor) !important;
            border-radius: 6px;
            font-size: 60px;
            color: #3a3b4b;
            padding: 0;
            text-align: center;
        }
    }
}

.err {
    color: #ff5858;
    font-size: 12px;
    line-height: 18px;
    margin-top: 6px;
    text-align: center;
}
</style>